#include "wx/wxprec.h"

#if wxUSE_FILEPICKERCTRL && defined(__WXGTK26__)

#include "wx/filepicker.h"
#include "wx/tooltip.h"

#include "wx/gtk/private.h"

// ============================================================================
// implementation
// ============================================================================

//-----------------------------------------------------------------------------
// wxFileButton
//-----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS( wxFileButton, wxButton )

bool wxFileButton::Create( wxWindow *parent, wxWindowID id,
                           const wxString &label, const wxString &path,
                           const wxString &message, const wxString &wildcard,
                           const wxPoint &pos, const wxSize &size,
                           long style, const wxValidator& validator,
                           const wxString &name ) {
  // we can't use the native button for wxFLP_SAVE pickers as it can only
  // open existing files and there is no way to create a new file using it
  if( !( style & wxFLP_SAVE ) && !gtk_check_version( 2, 6, 0 ) ) {
    // VERY IMPORTANT: this code is identic to relative code in wxDirButton;
    //                 if you find a problem here, fix it also in wxDirButton !
    m_needParent = true;
    m_acceptsFocus = true;
    if( !PreCreation( parent, pos, size ) ||
        !wxControl::CreateBase( parent, id, pos, size, style & wxWINDOW_STYLE_MASK,
                                validator, name ) ) {
      wxFAIL_MSG( wxT( "wxFileButton creation failed" ) );
      return false;
    }
    // create the dialog associated with this button
    // NB: unlike generic implementation, native GTK implementation needs to create
    //     the filedialog here as it needs to use gtk_file_chooser_button_new_with_dialog()
    SetWindowStyle( style );
    m_path = path;
    m_message = message;
    m_wildcard = wildcard;
    if( ( m_dialog = CreateDialog() ) == NULL ) {
      return false;
    }
    g_signal_connect( m_dialog->m_widget, "show", G_CALLBACK( gtk_grab_add ), NULL );
    g_signal_connect( m_dialog->m_widget, "hide", G_CALLBACK( gtk_grab_remove ), NULL );
    m_widget = gtk_file_chooser_button_new_with_dialog( m_dialog->m_widget );
    gtk_widget_show( GTK_WIDGET( m_widget ) );
    m_dialog->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
                       wxCommandEventHandler( wxFileButton::OnDialogOK ),
                       NULL, this );
    m_parent->DoAddChild( this );
    PostCreation( size );
    SetInitialSize( size );
  } else
    return wxGenericFileButton::Create( parent, id, label, path, message, wildcard,
                                        pos, size, style, validator, name );
  return true;
}

wxFileButton::~wxFileButton() {
  if( m_dialog ) {
    m_dialog->m_widget = NULL;
  }
}

void wxFileButton::OnDialogOK( wxCommandEvent& ev ) {
  if( ev.GetId() == wxID_OK ) {
    // ...update our path
    UpdatePathFromDialog( m_dialog );
    // ...and fire an event
    wxFileDirPickerEvent event( wxEVT_COMMAND_FILEPICKER_CHANGED, this, GetId(), m_path );
    GetEventHandler()->ProcessEvent( event );
  }
}

void wxFileButton::SetPath( const wxString &str ) {
  m_path = str;
  if( m_dialog ) {
    UpdateDialogPath( m_dialog );
  }
}

#endif


#if wxUSE_DIRPICKERCTRL && defined(__WXGTK26__)

#include <unistd.h> // chdir

extern "C" {
  static void gtk_dirbutton_currentfolderchanged_callback( GtkFileChooserButton *widget,
      wxDirButton *p ) {
    if( p->m_bIgnoreNextChange ) {
      p->m_bIgnoreNextChange = false;
      return;
    }
    wxASSERT( p );
    wxGtkString filename( gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( widget ) ) );
    p->UpdatePath( filename );
    if( p->HasFlag( wxDIRP_CHANGE_DIR ) ) {
      chdir( filename );
    }
    wxFileDirPickerEvent event( wxEVT_COMMAND_DIRPICKER_CHANGED, p, p->GetId(), p->GetPath() );
    p->GetEventHandler()->ProcessEvent( event );
  }
}

IMPLEMENT_DYNAMIC_CLASS( wxDirButton, wxButton )

bool wxDirButton::Create( wxWindow *parent, wxWindowID id,
                          const wxString &label, const wxString &path,
                          const wxString &message, const wxString &wildcard,
                          const wxPoint &pos, const wxSize &size,
                          long style, const wxValidator& validator,
                          const wxString &name ) {
  if( !gtk_check_version( 2, 6, 0 ) ) {
    m_needParent = true;
    m_acceptsFocus = true;
    if( !PreCreation( parent, pos, size ) ||
        !wxControl::CreateBase( parent, id, pos, size, style & wxWINDOW_STYLE_MASK,
                                validator, name ) ) {
      wxFAIL_MSG( wxT( "wxDirButtonGTK creation failed" ) );
      return false;
    }
    SetWindowStyle( style );
    m_message = message;
    m_wildcard = wildcard;
    if( ( m_dialog = CreateDialog() ) == NULL ) {
      return false;
    }
    SetPath( path );
    g_signal_connect( m_dialog->m_widget, "show", G_CALLBACK( gtk_grab_add ), NULL );
    g_signal_connect( m_dialog->m_widget, "hide", G_CALLBACK( gtk_grab_remove ), NULL );
    m_widget = gtk_file_chooser_button_new_with_dialog( m_dialog->m_widget );
    gtk_widget_show( GTK_WIDGET( m_widget ) );
    g_signal_connect( m_widget, "current-folder-changed",
                      G_CALLBACK( gtk_dirbutton_currentfolderchanged_callback ), this );
    m_parent->DoAddChild( this );
    PostCreation( size );
    SetInitialSize( size );
  } else
    return wxGenericDirButton::Create( parent, id, label, path, message, wildcard,
                                       pos, size, style, validator, name );
  return true;
}

wxDirButton::~wxDirButton() {
  if( m_dialog ) {
    m_dialog->m_widget = NULL;
  }
}

void wxDirButton::SetPath( const wxString& str ) {
  if( m_path == str ) {
    return;
  }
  m_path = str;
  m_bIgnoreNextChange = true;
  if( m_dialog ) {
    UpdateDialogPath( m_dialog );
  }
}

#endif
